package org.managarm.jmanaintlib.machine;

import org.managarm.jmanavalib.core.VaMthInfo;

public abstract class VmNativeCode extends VmCode {
	private class NativeExecutor extends VmExecutor {
		private final VmCell[] arguments;
		private boolean returnStatus;
		private VmCell returnValue;
		private int argumentPtr;
		
		public NativeExecutor() {
			int argcount = mthInfo.getArgumentCnt();
			if((mthInfo.flags0 & VaMthInfo.FLAG0_STATIC) != 0)
				argcount++;
			this.arguments = new VmCell[argcount];
		}
		
		@Override public final void pushArgument(VmCell object) {
			arguments[argumentPtr] = object;
			argumentPtr++;
		}
		
		@Override public final VmCode getCodeObject() {
			return VmNativeCode.this;
		}
		
		@Override public final boolean hasReturned() {
			return returnStatus;
		}
		
		@Override public VmCell getReturn() {
			return returnValue;
		}
		
		@Override public void processReturn(VmCell result) throws VmError {
			throw new VmError("Illegal virtual machine state");
		}
		@Override public void singleStep(VmState state)
				throws VmError {
			returnValue = runMethod(arguments);
			returnStatus = true;
		}
	}
	
	protected abstract VmCell runMethod(VmCell[] arguments)
			throws VmError;
	
	private final VaMthInfo mthInfo;
	
	protected VmNativeCode(VaMthInfo mthinfo) {
		this.mthInfo = mthinfo;
	}
	
	@Override public VaMthInfo getMthInfo() {
		return mthInfo;
	}
	@Override public final VmExecutor invoke() {
		return new NativeExecutor();
	}
}
